package com.jxdinfo.hussar.example.common.schedulingtask;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.jxdinfo.hussar.example.common.schedulingtask.dao.MdItemTypeMapper;
import com.jxdinfo.hussar.example.common.schedulingtask.model.MdItemType;
import com.jxdinfo.hussar.example.common.schedulingtask.scheduleutil.ScheduleUtils;
import com.jxdinfo.hussar.example.common.schedulingtask.service.MdItemTypeService;
import com.jxdinfo.hussar.example.common.schedulingtask.vo.MdItemTypeVO;
import lombok.AllArgsConstructor;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;


/**
 * @Author QiaoBin
 * @Date 2024/4/02 15:49
 * @Description  md_item_type_type物料产品分类表的定时任务
 */
@Component
@AllArgsConstructor
public class MdItemTypeScheduleTask {
    private static final Logger logger = LoggerFactory.getLogger(MdItemTypeScheduleTask.class);

    private MdItemTypeService mdItemTypeService;
    private MdItemTypeMapper mdItemTypeMapper;

    /**
     * @Author QiaoBin
     * @Date 2024/3/11 18:06
     * @Description 物料分类表的定时任务-md_item_type_type
     */
//    @Scheduled(cron = "*/25 * * * * ?")
    @Scheduled(cron = "0 0 2 * * ?") // 每天凌晨2点执行
    public void mdItemTypeTask() {
        logger.info("\n用友-物料分类表-定时任务-开始执行");
        LocalDateTime nowTime = LocalDateTime.now();
        synchronized ("mdItemTypeTask"){
            logger.info("用友-物料分类表-开始查询物料分类表中最大的同步时间");
            LocalDateTime scheduleDate = mdItemTypeMapper.selectMaxScheduleDate();
            String scheduleDateString = "";
            if (scheduleDate != null) {
                scheduleDateString = scheduleDate.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
            }
            //查询创建时间大于定时任务时间，查询出来后把所有数据全部插进去
            logger.info("\n用友-物料分类表-开始查询CBO_Category表中创建时间大于任务时间的数据,查询参数scheduleDateString={}", scheduleDateString);
            List<MdItemTypeVO> cboCategoryList = mdItemTypeMapper.selectMoreSchedule(scheduleDateString);
            logger.info("\n用友-物料分类表-结束查询CBO_Category表中创建时间大于任务时间的数据,查询结果cboCategoryList={}，size={}", cboCategoryList,cboCategoryList.size());
            // 结果集转成code-》对象的map集合
            logger.info("\n用友-物料分类表-开始把用友表中创建时间大于任务时间的数据转换成code、对象的map集合");
            Map<String, MdItemTypeVO> cboCategoryCodeToMap = cboCategoryList.stream().collect(Collectors.toMap(MdItemTypeVO::getItemTypeCode, t -> t));
            logger.info("\n用友-物料分类表-结束把用友表中创建时间大于任务时间的数据转换成code、对象的map集合，结果cboCategoryCodeToMap={}",cboCategoryCodeToMap);
            if (cboCategoryList.size() > 0) {
                ArrayList<MdItemType> mdItemTypeList = new ArrayList<>();
                for (int i = 0; i < cboCategoryList.size(); i++) {
                    logger.info("\n用友-物料分类表-当前循环次数i={}", i);
                    MdItemTypeVO mdItemTypeVO = cboCategoryList.get(i);
                    MdItemType mdItemType = new MdItemType();
                    mdItemType.setItemTypeId(mdItemTypeVO.getItemTypeId());
                    mdItemType.setItemTypeCode(mdItemTypeVO.getItemTypeCode());         // 物料类型编码
                    mdItemType.setItemTypeName(mdItemTypeVO.getItemTypeName());         // 物料类型名称
                    mdItemType.setEnableFlag("1");                                      // 是否生效
                    mdItemType.setItemOrProduct("PRODUCT");                                // 产品物料标识
                    // 父类型id
                    if (mdItemTypeVO.getItemTypeCode() != null && !"".equals(mdItemTypeVO.getItemTypeCode())) {
                        if (mdItemTypeVO.getItemTypeCode().length() == 2){
                            mdItemType.setParentTypeId(Long.parseLong("0"));
                        } else {
                            // 获取编码长度
                            String itemTypeCode = mdItemTypeVO.getItemTypeCode();
                            int length = itemTypeCode.length();
                            // 截取编码去掉后两位结果值
                            String parentCode = itemTypeCode.substring(0, length - 2);
                            // 获取code对应的id
                            Long itemTypeId = cboCategoryCodeToMap.get(parentCode).getItemTypeId();
                            mdItemType.setParentTypeId(itemTypeId);
                        }
                    }
                    mdItemType.setScheduleTime(nowTime);
                    mdItemType.setCreateBy(mdItemTypeVO.getCreateBy());
                    mdItemType.setCreateTime(mdItemTypeVO.getCreateTime());
                    mdItemType.setUpdateBy(mdItemTypeVO.getUpdateBy());
                    mdItemType.setUpdateTime(mdItemTypeVO.getUpdateTime());
                    mdItemType.setErpSortId(mdItemTypeVO.getItemTypeId());
                    logger.info("\n用友-物料分类表-开始向list中存入数据，数据mdItemType={},i={}", mdItemType,i);
                    mdItemTypeList.add(mdItemType);
                }
                // 设置所有的父类id
                for (MdItemType mdItemType : mdItemTypeList) {
                    List<Long> allParentIds = ScheduleUtils.getAllParentIds(mdItemTypeList, mdItemType.getItemTypeId());
                    StringBuilder stringBuilder = new StringBuilder();
                    for (int i = 0; i < allParentIds.size(); i++) {
                        Long aLong = allParentIds.get(i);
                        stringBuilder.append(aLong);
                        if (i < allParentIds.size() - 1) {
                            stringBuilder.append(",");
                        }
                    }
                    mdItemType.setAncestors(stringBuilder.toString());
                }
                logger.info("\n用友-物料分类表-开始向md_item_type表中插入数据，数据mdItemTypeList={}", mdItemTypeList);
                boolean b = mdItemTypeService.saveBatch(mdItemTypeList, 100);
                logger.info("\n用友-物料分类表-结束向md_item_type表中插入数据，插入结果b={}", b);
            }
            if (scheduleDate == null) {
                logger.info("\n用友-物料分类表-查询不到任务时间，说明一次也没有同步，之间原封不动的插入就行,也就不需要后续更新");
                return;
            }
            if (scheduleDate != null) {
                //查询CBO_Category和子表CBO_InventoryInfo中更新时间大于定时任务时间，查询出来后把所有数据全部更新进去
                logger.info("\n用友-物料分类表-开始查询CBO_Category表中更新时间大于任务时间，查询参数scheduleDateString={}", scheduleDateString);
                List<MdItemTypeVO> cboCategoryUpdateMoreScheduleList = mdItemTypeMapper.selectUpdateMoreSchedule(scheduleDateString);
                logger.info("\n用友-物料分类表-结束查询CBO_Category表中更新时间大于任务时间,查询结果masterAndInfoUpdateMoreScheduleList={},数量size={}", cboCategoryUpdateMoreScheduleList, cboCategoryUpdateMoreScheduleList.size());

                if (cboCategoryUpdateMoreScheduleList == null || cboCategoryUpdateMoreScheduleList.size() == 0) {
                    logger.info("\n用友-物料分类表-没有查询到更新时间大于任务时间的数据");
                    return;
                }
                // 结果集转成map集合
                logger.info("\n用友-物料分类表-开始把用友表中更新时间大于任务时间的数据转换成主键、对象的map集合");
                Map<Long, MdItemTypeVO> cboCategoryUpdateMap = cboCategoryUpdateMoreScheduleList.stream().collect(Collectors.toMap(MdItemTypeVO::getItemTypeId, t -> t));
                logger.info("\n用友-物料分类表-结束把用友表中更新时间大于任务时间的数据转换成主键、对象的map集合，结果cboCategoryUpdateMap={}",cboCategoryUpdateMap);
                logger.info("\n用友-物料分类表-开始把用友表中更新时间大于任务时间的数据转换成code、对象的map集合");
                Map<String, MdItemTypeVO> cboCategoryCodeToObjUpdateMap = cboCategoryUpdateMoreScheduleList.stream().collect(Collectors.toMap(MdItemTypeVO::getItemTypeCode, t -> t));
                logger.info("\n用友-物料分类表-结束把用友表中更新时间大于任务时间的数据转换成code、对象的map集合，结果cboCategoryCodeToObjUpdateMap={}",cboCategoryCodeToObjUpdateMap);
                // 获取CBO_Category和子表CBO_InventoryInfo更新过的主键
                logger.info("\n用友-物料分类表-开始获取用友表中更新时间大于任务时间的数据的主键");
                List<Long> itemTypeIdList = cboCategoryUpdateMoreScheduleList.stream().map(MdItemTypeVO::getItemTypeId).collect(Collectors.toList());
                logger.info("\n用友-物料分类表-CBO_Category更新时间大于任务时间的主键集合itemTypeIdList={},size={}", itemTypeIdList, itemTypeIdList.size());
                // 重新设置值并更新进去
                logger.info("\n用友-物料分类表-开始查询md_item_type_type中erp主键=CBO_Category表中主键的数据,参数itemTypeIdList={}", itemTypeIdList);
                QueryWrapper<MdItemType> mdItemTypeWrapper = new QueryWrapper<>();
                mdItemTypeWrapper.in("erp_sort_id",itemTypeIdList);
                mdItemTypeWrapper.eq("deleted_flag",0);
                List<MdItemType> mdItemTypeUpdateList = mdItemTypeMapper.selectList(mdItemTypeWrapper);
                logger.info("\n用友-物料分类表-结束查询md_item_type中erp主键=CBO_Category表中主键的数据,结果mdItemTypeUpdateList={},size={}", mdItemTypeUpdateList, mdItemTypeUpdateList.size());
                if (mdItemTypeUpdateList.size() > 0) {
                    ArrayList<MdItemType> updateItemTypeList = new ArrayList<>();
                    for (int i = 0; i < mdItemTypeUpdateList.size(); i++) {
                        logger.info("\n用友-物料分类表-当前更新时间大于任务时间，md_item_type表更新，次数i={}", i);
                        MdItemType mdItemType = mdItemTypeUpdateList.get(i);
                        Long currentMasterId = mdItemType.getErpSortId();
                        MdItemTypeVO mdItemTypeVO = cboCategoryUpdateMap.get(currentMasterId);
                        mdItemType.setItemTypeName(mdItemTypeVO.getItemTypeName());        // 物料类型名称
                        mdItemType.setItemTypeCode(mdItemTypeVO.getItemTypeCode());        // 物料类型编码
                        mdItemType.setEnableFlag("1");                                      // 是否生效
                        mdItemType.setItemOrProduct("ITEM");                                // 产品物料标识
                        // 父类型id
                        if (mdItemTypeVO.getItemTypeCode() != null && !"".equals(mdItemTypeVO.getItemTypeCode())) {
                            if (mdItemTypeVO.getItemTypeCode().length() == 2){
                                mdItemType.setParentTypeId(Long.parseLong("0"));
                            } else {
                                // 获取编码长度
                                String itemTypeCode = mdItemTypeVO.getItemTypeCode();
                                int length = itemTypeCode.length();
                                // 截取编码去掉后两位结果值
                                String parentCode = itemTypeCode.substring(0, length - 2);
                                Long itemTypeId = cboCategoryCodeToObjUpdateMap.get(parentCode).getItemTypeId();
                                mdItemType.setParentTypeId(itemTypeId);
                            }
                        }
                        mdItemType.setScheduleTime(nowTime);
                        mdItemType.setCreateBy(mdItemTypeVO.getCreateBy());
                        mdItemType.setCreateTime(mdItemTypeVO.getCreateTime());
                        mdItemType.setUpdateBy(mdItemTypeVO.getUpdateBy());
                        mdItemType.setUpdateTime(mdItemTypeVO.getUpdateTime());
                        logger.info("\n用友-物料分类表-向updateItemTypeList中存储待要更新的物料分类表信息,mdItemType={}", mdItemType);
                        updateItemTypeList.add(mdItemType);
                    }
                    // 设置所有的父类id
                    for (MdItemType mdItemType : updateItemTypeList) {
                        List<Long> allParentIds = ScheduleUtils.getAllParentIds(updateItemTypeList, mdItemType.getItemTypeId());
                        StringBuilder stringBuilder = new StringBuilder();
                        for (int i = 0; i < allParentIds.size(); i++) {
                            Long aLong = allParentIds.get(i);
                            stringBuilder.append(aLong);
                            if (i < allParentIds.size() - 1) {
                                stringBuilder.append(",");
                            }
                        }
                        mdItemType.setAncestors(stringBuilder.toString());
                    }
                    logger.info("\n用友-物料分类表-开始更新md_item_type数据,列表updateItemTypeList={}", updateItemTypeList);
                    boolean u = mdItemTypeService.updateBatchById(updateItemTypeList);
                    logger.info("\n用友-物料分类表-结束更md_item_type数据,更新结果u={}", u);
                }
            }
        }
        logger.info("\n用友-物料分类表-定时任务-结束执行");
    }

/*    public static List<Long> getAllParentIds(List<MdItemType> mdItemTypeList, Long childId) {
        List<Long> parentIds = new ArrayList<>();
        for (MdItemType obj : mdItemTypeList) {
            if (obj.getItemTypeId() == childId) {
                parentIds.add(obj.getParentTypeId());
                if (obj.getParentTypeId() != null || "".equals(obj.getParentTypeId())) {
                    parentIds.addAll(getAllParentIds(mdItemTypeList, obj.getParentTypeId()));
                }
                break;
            }
        }
        return parentIds;
    }*/
}
